package UI.Table;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.util.HashMap;
import java.util.Random;

import javax.swing.JLabel;
import javax.swing.JTextField;

//@author A0103535R
/*********************** Abstract Class DSTaskTableCellColoredLabel *******************/
public class DSTaskTableCellColoredLabel extends JLabel {
	private static final long serialVersionUID = 1L;
	protected static HashMap<String, Color> _colorStore = new HashMap<>();
	
	public static final int DATE_TYPE_PASSED = -1;
	public static final int DATE_TYPE_FAR = 1;
	
	private static final int DATE_LEFT_DURATION_MAXIMUM = 361578027/10000;
	private static final int DATE_LEFT_DURATION_MINIMUM = 0;
	private static final int DSTASKTABLECELLCOLORLABEL_ROUNDED_CORNER_RADIUS = 8;

	private Color _backgroundColor = new Color(82, 89, 106, 150);
	private Color _roundedBorderColor = new Color(82, 89, 106, 150);
	private int _width = 0, _height = 0;

	/**
	 * This is the constructor of DSTaskTableCellColoredLabel of index
	 */
	public DSTaskTableCellColoredLabel(int index) {
		super(String.format("%d", index));
		initIndexLabel();
	}

	/**
	 * This is the constructor of DSTaskTableCellColoredLabel of date
	 */
	public DSTaskTableCellColoredLabel(String date, int timeLeft) {
		super(date);
		initDateLabel(timeLeft);
	}

	/**
	 * This is the constructor of DSTaskTableCellColoredLabel of tag
	 */
	public DSTaskTableCellColoredLabel(String text) {
		super(text);
		initTagLabel();
	}

	/**
	 * This function is used to initialize the label of index
	 */
	private void initIndexLabel() {
		setForeground(new Color(255, 255, 255, 255));
		setHorizontalAlignment(JTextField.CENTER);
		setVerticalAlignment(JTextField.CENTER);
		setFont(new Font("Calibri", Font.PLAIN, 13));
		_backgroundColor = new Color(82, 89, 106, 150);
		_roundedBorderColor = new Color(52, 60, 71, 100);
	}

	/**
	 * This function is used to initialize the label of date
	 * 
	 * @param timeLeft
	 * 			time left before date and used for the color of date
	 */
	private void initDateLabel(int timeLeft) {
		setForeground(new Color(255, 255, 255, 255));
		setHorizontalAlignment(JTextField.CENTER);
		setVerticalAlignment(JTextField.CENTER);
		setFont(new Font("Calibri", Font.PLAIN, 13));
		_backgroundColor = getDateLabelColor(timeLeft);
		_roundedBorderColor = _backgroundColor;
	}

	/**
	 * This function is used to initialize the label of tag
	 */
	private void initTagLabel() {
		setForeground(new Color(255, 255, 255, 255));
		setHorizontalAlignment(JTextField.CENTER);
		setVerticalAlignment(JTextField.CENTER);
		setFont(new Font("Calibri", Font.PLAIN, 12));
		Color color;
		if (_colorStore.containsKey(getText())) {
			color = _colorStore.get(getText());
		} else {
			color = getRandomColor();
			_colorStore.put(getText(), color);
		}
		_backgroundColor = color;
		_roundedBorderColor = color;
	}

	/**
	 * This function is used to get the color of date label 
	 * 
	 * @param timeLeft
	 * 			how much time left before its date
	 * 
	 * @return the color of date label
	 */
	private Color getDateLabelColor(int timeLeft) {
		Color color;
		if (timeLeft > DATE_LEFT_DURATION_MAXIMUM || timeLeft == DATE_TYPE_FAR) {
			color = new Color(100, 100, 100, 255);
		} else if (timeLeft == DATE_TYPE_PASSED) {
			color = new Color(100, 100, 100, 80);
		} else if (timeLeft <= DATE_LEFT_DURATION_MINIMUM) {
			color = new Color(166, 77, 121, 255);
		} else {
			color = getColorWithTimeLeft(timeLeft);
		}
		return color;
	}

	/**
	 * This function is used to get random color
	 * 
	 * @return the random color
	 */
	private Color getRandomColor() {
		Random random = new Random();
		return new Color(80 + random.nextInt(150), 70 + random.nextInt(120),
				70 + random.nextInt(100), 255);

	}

	/**
	 * This function is used to compute the color of date label according to its time
	 * 
	 * @param timeLeft
	 * 			how much time left before its date
	 * 
	 * @return color
	 */
	private Color getColorWithTimeLeft(int timeLeft) {
		int red = (int) (timeLeft * 1.0 / DATE_LEFT_DURATION_MAXIMUM * 145);
		int green = (int) (timeLeft * 1.0 / DATE_LEFT_DURATION_MAXIMUM * 8);
		int blue = (int) (timeLeft * 1.0 / DATE_LEFT_DURATION_MAXIMUM * 8);
		return new Color(245 - red, 94 - green, 108 - blue, 255);
	}

	/**
	 * This function is used to set the color of date label as done color
	 */
	public void setDateDoneColor() {
		Color color = new Color(82, 89, 106, 150);
		setForeground(new Color(179, 181, 189));
		_backgroundColor = color;
		_roundedBorderColor = color;
	}

	/**
	 * This function is used to set the color of index label as done color
	 */
	public void setIndexDoneColor() {
		Color color = new Color(65, 71, 83);
		setForeground(new Color(179, 181, 189));
		_backgroundColor = color;
		_roundedBorderColor = color;
	}

	/**
	 * This function is used to resize the label according to its text
	 */
	public void resize() {
		_width = getFontMetrics(getFont()).stringWidth(getText()) + 15;
		_height = getFontMetrics(getFont()).getHeight();
		setPreferredSize(new Dimension(_width, _height));
		setMinimumSize(new Dimension(_width, _height));
	}

	/**
	 * This function is used to get the width of label
	 * 
	 * @return the width
	 */
	public int getWidth() {
		return _width;
	}

	/**
	 * This function is used to get the height of label
	 * 
	 * @return the height 
	 */
	public int getHeight() {
		return _height;
	}

	/**
	 * This function is used to paint the components on label
	 * 
	 * @param g
	 * 		graphics of painting
	 */
	@Override
	protected void paintComponent(Graphics g) {
		int x = 0;
		int y = 0;
		int w = getWidth();
		int h = getHeight();
		int arc = DSTASKTABLECELLCOLORLABEL_ROUNDED_CORNER_RADIUS;

		// Draw Background
		Graphics2D g2 = (Graphics2D) g.create();
		g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
				RenderingHints.VALUE_ANTIALIAS_ON);
		g2.setColor(_backgroundColor);
		g2.fillRoundRect(x, y, w, h, arc, arc);

		// Draw Border
		g2.setStroke(new BasicStroke(2f));
		g2.setColor(_roundedBorderColor);
		g2.drawRoundRect(x + 1, y + 1, w - 2, h - 2, arc, arc);
		g2.dispose();
		super.paintComponent(g);
	}
}
